home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).adf / C Compiler / genstmt.c < prev    next >
C/C++ Source or Header  |  1987-03-04  |  11KB  |  391 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *    all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.  
  25. int     breaklab;
  26. int     contlab;
  27. int     retlab;
  28.  
  29. extern TYP              stdfunc;
  30. extern struct amode     push[], pop[];
  31.  
  32. struct amode    *makedreg(r)
  33. /*
  34.  *      make an address reference to a data register.
  35.  */
  36. int     r;
  37. {       struct amode    *ap;
  38.         ap = xalloc(sizeof(struct amode));
  39.         ap->mode = am_dreg;
  40.         ap->preg = r;
  41.         return ap;
  42. }
  43.  
  44. struct amode    *makeareg(r)
  45. /*
  46.  *      make an address reference to an address register.
  47.  */
  48. int     r;
  49. {       struct amode    *ap;
  50.         ap = xalloc(sizeof(struct amode));
  51.         ap->mode = am_areg;
  52.         ap->preg = r;
  53.         return ap;
  54. }
  55.  
  56. struct amode    *make_mask(mask)
  57. /*
  58.  *      generate the mask address structure.
  59.  */
  60. int     mask;
  61. {       struct amode    *ap;
  62.         ap = xalloc(sizeof(struct amode));
  63.         ap->mode = am_mask;
  64.         ap->offset = mask;
  65.         return ap;
  66. }
  67.  
  68. struct amode    *make_direct(i)
  69. /*
  70.  *      make a direct reference to an immediate value.
  71.  */
  72. int     i;
  73. {       return make_offset(makenode(en_icon,i,0));
  74. }
  75.  
  76. struct amode    *make_strlab(s)
  77. /*
  78.  *      generate a direct reference to a string label.
  79.  */
  80. char    *s;
  81. {       struct amode    *ap;
  82.         ap = xalloc(sizeof(struct amode));
  83.         ap->mode = am_direct;
  84.         ap->offset = makenode(en_nacon,s,0);
  85.         return ap;
  86. }
  87.  
  88. genwhile(stmt)
  89. /*
  90.  *      generate code to evaluate a while statement.
  91.  */
  92. struct snode    *stmt;
  93. {       int     lab1, lab2;
  94.         initstack();            /* initialize temp registers */
  95.         lab1 = contlab;         /* save old continue label */
  96.         lab2 = breaklab;        /* save old break label */
  97.         contlab = nextlabel++;  /* new continue label */
  98.         gen_label(contlab);
  99.         if( stmt->s1 != 0 )      /* has block */
  100.                 {
  101.                 breaklab = nextlabel++;
  102.                 initstack();
  103.                 falsejp(stmt->exp,breaklab);
  104.                 genstmt(stmt->s1);
  105.                 gen_code(op_bra,0,make_label(contlab),0);
  106.                 gen_label(breaklab);
  107.                 breaklab = lab2;        /* restore old break label */
  108.                 }
  109.         else                            /* no loop code */
  110.                 {
  111.                 initstack();
  112.                 truejp(stmt->exp,contlab);
  113.                 }
  114.         contlab = lab1;         /* restore old continue label */
  115. }
  116.  
  117. gen_for(stmt)
  118. /*
  119.  *      generate code to evaluate a for loop
  120.  */
  121. struct snode    *stmt;
  122. {       int     old_break, old_cont, exit_label, loop_label;
  123.         old_break = breaklab;
  124.         old_cont = contlab;
  125.         loop_label = nextlabel++;
  126.         exit_label = nextlabel++;
  127.         contlab = loop_label;
  128.         initstack();
  129.         if( stmt->label != 0 )
  130.                 gen_expr(stmt->label,F_ALL | F_NOVALUE
  131.                         ,natural_size(stmt->label));
  132.         gen_label(loop_label);
  133.         initstack();
  134.         if( stmt->exp != 0 )
  135.                 falsejp(stmt->exp,exit_label);
  136.         if( stmt->s1 != 0 )
  137.         {
  138.                 breaklab = exit_label;
  139.                 genstmt(stmt->s1);
  140.         }
  141.         initstack();
  142.         if( stmt->s2 != 0 )
  143.                 gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
  144.         gen_code(op_bra,0,make_label(loop_label),0);
  145.         breaklab = old_break;
  146.         contlab = old_cont;
  147.         gen_label(exit_label);
  148. }
  149.  
  150. genif(stmt)
  151. /*
  152.  *      generate code to evaluate an if statement.
  153.  */
  154. struct snode    *stmt;
  155. {       int     lab1, lab2, oldbreak;
  156.         lab1 = nextlabel++;     /* else label */
  157.         lab2 = nextlabel++;     /* exit label */
  158.         oldbreak = breaklab;    /* save break label */
  159.         initstack();            /* clear temps */
  160.         falsejp(stmt->exp,lab1);
  161.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  162.                 if( stmt->s2 != 0 )
  163.                         breaklab = lab2;
  164.                 else
  165.                         breaklab = lab1;
  166.         genstmt(stmt->s1);
  167.         if( stmt->s2 != 0 )             /* else part exists */
  168.                 {
  169.                 gen_code(op_bra,0,make_label(lab2),0);
  170.                 gen_label(lab1);
  171.                 if( stmt->s2 == 0 || stmt->s2->next == 0 )
  172.                         breaklab = oldbreak;
  173.                 else
  174.                         breaklab = lab2;
  175.                 genstmt(stmt->s2);
  176.                 gen_label(lab2);
  177.                 }
  178.         else                            /* no else code */
  179.                 gen_label(lab1);
  180.         breaklab = oldbreak;
  181. }
  182.  
  183. gendo(stmt)
  184. /*
  185.  *      generate code for a do - while loop.
  186.  */
  187. struct snode    *stmt;
  188. {       int     oldcont, oldbreak;
  189.         oldcont = contlab;
  190.         oldbreak = breaklab;
  191.         contlab = nextlabel++;
  192.         gen_label(contlab);
  193.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  194.                 {
  195.                 breaklab = nextlabel++;
  196.                 genstmt(stmt->s1);      /* generate body */
  197.                 initstack();
  198.                 truejp(stmt->exp,contlab);
  199.                 gen_label(breaklab);
  200.                 }
  201.         else
  202.                 {
  203.                 genstmt(stmt->s1);
  204.                 initstack();
  205.                 truejp(stmt->exp,contlab);
  206.                 }
  207.         breaklab = oldbreak;
  208.         contlab = oldcont;
  209. }
  210.  
  211. call_library(lib_name)
  212. /*
  213.  *      generate a call to a library routine.
  214.  */
  215. char    *lib_name;
  216. {       SYM     *sp;
  217.         sp = gsearch(lib_name);
  218.         if( sp == 0 )
  219.                 {
  220.                 ++global_flag;
  221.                 sp = xalloc(sizeof(SYM));
  222.                 sp->tp = &stdfunc;
  223.                 sp->name = lib_name;
  224.                 sp->storage_class = sc_external;
  225.                 insert(sp,&gsyms);
  226.                 --global_flag;
  227.                 }
  228.         gen_code(op_jsr,0,make_strlab(lib_name),0);
  229. }
  230.  
  231. genswitch(stmt)
  232. /*
  233.  *      generate a linear search switch statement.
  234.  */
  235. struct snode    *stmt;
  236. {       int             curlab;
  237.         struct snode    *defcase;
  238.         struct amode    *ap;
  239.         curlab = nextlabel++;
  240.         defcase = 0;
  241.         initstack();
  242.         ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
  243.         if( ap->preg != 0 )
  244.                 gen_code(op_move,4,ap,makedreg(0));
  245.         stmt = stmt->s1;
  246.         call_library("c%switch");
  247.         while( stmt != 0 )
  248.                 {
  249.                 if( stmt->s2 )          /* default case ? */
  250.                         {
  251.                         stmt->label = curlab;
  252.                         defcase = stmt;
  253.                         }
  254.                 else
  255.                         {
  256.                         gen_code(op_dc,4,make_label(curlab),
  257.                                 make_direct(stmt->label));
  258.                         stmt->label = curlab;
  259.                         }
  260.                 if( stmt->s1 != 0 && stmt->next != 0 )
  261.                         curlab = nextlabel++;
  262.                 stmt = stmt->next;
  263.                 }
  264.         if( defcase == 0 )
  265.                 gen_code(op_dc,4,make_direct(0),make_label(breaklab));
  266.         else
  267.                 gen_code(op_dc,4,make_direct(0),make_label(defcase->label));
  268. }
  269.  
  270. gencase(stmt)
  271. /*
  272.  *      generate all cases for a switch statement.
  273.  */
  274. struct snode    *stmt;
  275. {       while( stmt != 0 )
  276.                 {
  277.                 if( stmt->s1 != 0 )
  278.                         {
  279.                         gen_label(stmt->label);
  280.                         genstmt(stmt->s1);
  281.                         }
  282.                 else if( stmt->next == 0 )
  283.                         gen_label(stmt->label);
  284.                 stmt = stmt->next;
  285.                 }
  286. }
  287.  
  288. genxswitch(stmt)
  289. /*
  290.  *      analyze and generate best switch statement.
  291.  */
  292. struct snode    *stmt;
  293. {       int     oldbreak;
  294.         oldbreak = breaklab;
  295.         breaklab = nextlabel++;
  296.         genswitch(stmt);
  297.         gencase(stmt->s1);
  298.         gen_label(breaklab);
  299.         breaklab = oldbreak;
  300. }
  301.  
  302. genreturn(stmt)
  303. /*
  304.  *      generate a return statement.
  305.  */
  306. struct snode    *stmt;
  307. {       struct amode    *ap;
  308.         if( stmt != 0 && stmt->exp != 0 )
  309.                 {
  310.                 initstack();
  311.                 ap = gen_expr(stmt->exp,F_ALL,4);
  312.                 if( ap->mode != am_dreg || ap->preg != 0 )
  313.                         gen_code(op_move,4,ap,makedreg(0));
  314.                 }
  315.         if( retlab == -1 )
  316.                 {
  317.                 retlab = nextlabel++;
  318.                 gen_label(retlab);
  319.                 if( save_mask != 0 )
  320.                         gen_code(op_movem,4,pop,make_mask(save_mask));
  321.                 gen_code(op_unlk,0,makeareg(6),0);
  322.                 gen_code(op_rts,0,0,0);
  323.                 }
  324.         else
  325.                 gen_code(op_bra,0,make_label(retlab),0);
  326. }
  327.  
  328. genstmt(stmt)
  329. /*
  330.  *      genstmt will generate a statement and follow the next pointer
  331.  *      until the block is generated.
  332.  */
  333. struct snode    *stmt;
  334. {       while( stmt != 0 )
  335.                 {
  336.                 switch( stmt->stype )
  337.                         {
  338.                         case st_label:
  339.                                 gen_label(stmt->label);
  340.                                 break;
  341.                         case st_goto:
  342.                                 gen_code(op_bra,0,make_label(stmt->label),0);
  343.                                 break;
  344.                         case st_expr:
  345.                                 initstack();
  346.                                 gen_expr(stmt->exp,F_ALL | F_NOVALUE,
  347.                                         natural_size(stmt->exp));
  348.                                 break;
  349.                         case st_return:
  350.                                 genreturn(stmt);
  351.                                 break;
  352.                         case st_if:
  353.                                 genif(stmt);
  354.                                 break;
  355.                         case st_while:
  356.                                 genwhile(stmt);
  357.                                 break;
  358.                         case st_for:
  359.                                 gen_for(stmt);
  360.                                 break;
  361.                         case st_continue:
  362.                                 gen_code(op_bra,0,make_label(contlab),0);
  363.                                 break;
  364.                         case st_break:
  365.                                 gen_code(op_bra,0,make_label(breaklab),0);
  366.                                 break;
  367.                         case st_switch:
  368.                                 genxswitch(stmt);
  369.                                 break;
  370.                         default:
  371.                                 printf("DIAG - unknown statement.\n");
  372.                                 break;
  373.                         }
  374.                 stmt = stmt->next;
  375.                 }
  376. }
  377.  
  378. genfunc(stmt)
  379. /*
  380.  *      generate a function body.
  381.  */
  382. struct snode    *stmt;
  383. {       retlab = contlab = breaklab = -1;
  384.         if( lc_auto & 1 )    /* if frame size odd */
  385.             ++lc_auto;        /* make it even */
  386.         gen_code(op_link,0,makeareg(6),make_immed(-lc_auto));
  387.         opt1(stmt);
  388.         genstmt(stmt);
  389.         genreturn(0);
  390. }
  391.